<?php
/**
 * promotion service
 */

require_once '../app/core/services/BaseService.php';
require_once '../app/models/PromotionDao.php';
require_once '../app/models/PromotionConditionDao.php';
require_once '../app/models/PromotionActionDao.php';
require_once '../app/models/CategoryDao.php';
require_once '../app/models/OrderPromotionDao.php';
require_once '../app/models/ApplyGiftLogDao.php';
require_once '../app/models/UserDao.php';

class PromotionImplService extends BaseService {

    private $promotionDao;

    private $promotionConditionDao;

    private $promotionActionDao;
    
    private $categoryDao;
    
    private $productItemDao;
    
    private $orderPromotionDao;
    
    private $applyGiftLogDao;
    
    private $userDao;

    public function __construct () {
        parent::__construct();
        $this->promotionDao = new PromotionDao($this->dbUtil);
        $this->promotionConditionDao = new PromotionConditionDao($this->dbUtil);
        $this->promotionActionDao = new PromotionActionDao($this->dbUtil);
        $this->categoryDao = new CategoryDao($this->dbUtil);
        $this->productItemDao = new ProductItemDao($this->dbUtil);
        $this->orderPromotionDao = new OrderPromotionDao($this->dbUtil);
        $this->applyGiftLogDao = new ApplyGiftLogDao($this->dbUtil);
        $this->userDao = new UserDao($this->dbUtil);
    }
    
    public function getAutoPromotion(){
        $codes = array();
        $promotions = $this->promotionDao->getAutoPromotions();
        if(empty($promotions)){
            return "";
        }
        foreach($promotions as $promotion){
            $promotionId = $promotion['id'];
            $promotionCodes = $this->promotionConditionDao->getConditionByType($promotionId,7);
            if(!empty($promotionCodes) && !empty($promotionCodes[0]['code_value'])){
                $codes[] = $promotionCodes[0]['code_value'];
            }
        }
        if(empty($codes)){
            return "";
        }
        return implode(",",$codes);
    }

    public function impl($subTotal,$productItems,$quantities,$prices,$userId,$firstPromotion,$stackable,$couponCode) {
        if($firstPromotion == false && $stackable == false) {
            return false;
        }
        $promotion = $this->promotionDao->getPromotionByCouponCode($couponCode);
        
        if(empty($promotion)) {
            return false;
        }
        if($firstPromotion == false && $promotion['stackable'] == false) {
            return false;
        }
        
        //check user restriction
        $customerConditionArray = array();
        $customerConditions = $this->promotionConditionDao->getConditionByType($promotion['id'], 6);
        if(!empty($customerConditions)){
            foreach($customerConditions as $customerCondition){
                $customerConditionArray[] = intval($customerCondition['condition_value']);          
	        }
	        if(!in_array($userId,$customerConditionArray)){
	            return false;
	        }        	
        }
        //check total used
        $totalUses = $promotion['total_uses'];
        $usedCount = $promotion['used'];
        if(!empty($totalUses)){
        	if($usedCount >= $totalUses){
        		return false;
        	}
        }
        //check per use of customer
        $perUses = $promotion['uses_per_customer'];
        if(!empty($perUses)){
        	$usedCountPerCustomer = $this->getUsedCountByCustomerAndPromotion($userId,$promotion['id']);
        	if($usedCountPerCustomer >= $perUses){
        		return false;
        	}
        }
        
        //Check when coupon code is binded with a user
        if($promotion['promotion_condition_type'] == 7 && !empty($promotion['condition_value'])){
    		$conditionUserId = intval($promotion['condition_value']);
    		
    		if($conditionUserId>0 && $userId != $conditionUserId){
    			return false;
    		}
    	}
        
        
        
       //check user certf and user rank
        $user = $this->userDao->getUserById($userId);
        $certfArr = array();
        $customerCertfConditions = $this->promotionConditionDao->getConditionByType($promotion['id'], 8);
        if(!empty($customerCertfConditions)){
        	foreach($customerCertfConditions as $customerCertfCondition){
        		$certfArr[] = intval($customerCertfCondition['condition_value']);  
        	}
        	if(!in_array($user[0]['certf'],$certfArr)){
	            return false;
	        }   
        }
        $rankArr = array();
        $customerRankConditions = $this->promotionConditionDao->getConditionByType($promotion['id'], 9);
        if(!empty($customerRankConditions)){
        	foreach($customerRankConditions as $customerRankCondition){
        		$rankArr[] = intval($customerRankCondition['condition_value']);  
        	}
        	if(!in_array($user[0]['rank'],$rankArr)){
	            return false;
	        }   
        }
       
       
        //execute promotion
        return $this->executeWithCode($promotion,$subTotal,$productItems,$quantities,$prices,$userId,$couponCode);
    }

    protected function executeWithCode($promotion,$subTotal,$productItems,$quantities,$prices,$userId,$couponCode="") {
    	$promtionType = $promotion['promotion_type'];
        if($promtionType == 2){
            $result = $this->excuteProductPromotion($promotion,$subTotal,$productItems,$quantities,$prices,$userId,$couponCode);
        }else if($promtionType == 3){
        	$result = $this->excuteOrderPromotion($promotion, $subTotal, $productItems, $quantities, $prices,$userId,$couponCode);
        }else if($promtionType == 4){
            
        }
        return $result;
    }

    protected function excuteProductPromotion($promotion,$subTotal,$productItems,$quantities,$prices,$userId,$couponCode="") {
        //product item 's detail of promotion
        $productItemsPromotion = array();
        //product item condition
        $prodcutConditions = $this->promotionConditionDao->getConditionByType($promotion['id'], 1);
        //category condition
        $categoryConditions = $this->promotionConditionDao->getConditionByType($promotion['id'], 2);
        //promotion actions
        $promotionActions = $this->promotionActionDao->getActionBypromotionid($promotion['id']);
        if(empty($promotionActions)) {
            return false;
        }
        $promotionAction = $promotionActions[0];
        //discount total
        $discountAllTotal = 0;

        $productConditionsArr = array();

        foreach($prodcutConditions as $prodcutCondition) {
            $productConditionsArr[] = intval($prodcutCondition['condition_value']);
        }
        //get category 's product item
        foreach($categoryConditions as $categoryCondition) {
        	$productConditionsArrTemp = array();
	        $productConditionsArrTemp = $this->getItemId($categoryCondition['condition_value']);
            if(!empty($productConditionsArrTemp)){
            	 foreach($productConditionsArrTemp as $productConditionTemp){
            	 	 $productConditionsArr[] = $productConditionTemp;
            	 }
            }
        }
        //implement action start
        $validPromotion = false;

        foreach($productItems as $productItem) {
            $validProduct = false;
            if(empty($productConditionsArr)) {
                $validProduct = true;
            }else if(in_array($productItem,$productConditionsArr)) {
                    $validProduct = true;
            }
            if(!$validProduct) {
                continue;
            }
            $actionType = $promotionAction['promotion_action_type'];
            $normalPrice = $prices[$productItem];
            $quantity = $quantities[$productItem];
            if($actionType == 1 || $actionType == 2) {
                $actionValue = $promotionAction['action_value'];
                $discountedPrice = $this-> getPromotionPrice($actionType, $actionValue, $normalPrice);
                if($discountedPrice < 0) {
                    continue;
                }
                $discountTotal = number_format(($normalPrice-$discountedPrice)*$quantity,2);
                $discountAllTotal += $discountTotal;
                $productItemsPromotion[$productItem] = array(
                    'discountTotal' => $discountTotal,
                    'isFreeShipping' => 0,
                );
                $validPromotion = true;
            }else if($actionType == 3) {
                $productItemsPromotion[$productItem] = array(
                    'discountTotal' => 0,
                    'isFreeShipping' => 1,
                );
                $validPromotion = true;
            }
        }
        //if $discountAllTotal > $subtotal then return false
        if($discountAllTotal > $subTotal){
            return false;
        }
        if($validPromotion === false){
            return false;
        }
        return array('itemsDiscount' => $productItemsPromotion,
                     'discountAllTotal' => $discountAllTotal,
                     'stackable' => $promotion['stackable'],
                     'promotionId' =>  $promotion['id'],
                     'couponCode' =>  $couponCode,
                     'title' => $promotion['name']
                    );
    }

    protected function excuteOrderPromotion($promotion,$subTotal,$productItems,$quantities,$prices,$userId,$couponCode="") {
    	
    	 
    	//product item 's detail of promotion
        $productItemsPromotion = array();
        //subtotal conditions
        $subtotalConditions = $this->promotionConditionDao->getConditionByType($promotion['id'],3);
        //promotion actions
        $promotionActions = $this->promotionActionDao->getActionBypromotionid($promotion['id']);
       
        if(empty($promotionActions)) {
            return false;
        }
        
        $promotionAction = $promotionActions[0];
        //all total price
        $allTotalPrice = 0;
        //discount total
        $discountAllTotal = 0;
       
        
        //promotion condition
        $subtotalCondition = $subtotalConditions[0];
        $coditionType = $subtotalCondition['promotion_condition_type'];
        $conditionOperator = $subtotalCondition['condition_value'];
        $conditionValue = $subtotalCondition['condition_second_value'];
        if(!empty($subtotalCondition)){
        	$validPromotion = false;
        }
        //if($coditionType == 3){
            switch ($conditionOperator) {
                case 1:
                    if($subTotal == $conditionValue) {
                        $validPromotion = true;
                    }
                    break;
                case 2:
                    if($subTotal > $conditionValue) {
                        $validPromotion = true;
                    }
                    break;
                case 3:
                    if($subTotal < $conditionValue) {
                        $validPromotion = true;
                    }
                    break;
                case 4:
                    if($subTotal >= $conditionValue) {
                        $validPromotion = true;
                    }
                    break;
                case 5:
                    if($subTotal <= $conditionValue) {
                        $validPromotion = true;
                    }
                    break;
            }
            if(!empty($subtotalCondition) && $validPromotion === false){
                return false;
            }
            //implement action start           
            $actionType = $promotionAction['promotion_action_type'];
            $actionValue = $promotionAction['action_value'];     
                   
            foreach($productItems as $productItem) {
                if($actionType == 1 || $actionType == 2) {
                    $normalPrice = $prices[$productItem];
                    $quantity = $quantities[$productItem];
                    $allTotalPrice += $normalPrice * $quantity;
                }
            }    
               
            if($actionType == 1) {
                $discountAllTotal = number_format($subTotal * $actionValue * 0.01,2);     
            } else if($actionType == 2) {
                $discountAllTotal = number_format($actionValue,2);
            }  
                      
            foreach($productItems as $productItem) {
                if($actionType == 1 || $actionType == 2) {
                    $normalPrice = $prices[$productItem];
                    $quantity = $quantities[$productItem];
//                    $discountedPrice = $this-> getPromotionPrice($actionType, $actionValue, $normalPrice);
//                    if($discountedPrice < 0) {
//                        continue;
//                    }
                    $discountTotal = number_format($discountAllTotal*(($normalPrice*$quantity)/$allTotalPrice),2);
//                    $discountAllTotal += $discountTotal;
                    $productItemsPromotion[$productItem] = array(
                        'discountTotal' => $discountTotal,
                        'isFreeShipping' => 0,
                    );
                }else if($actionType == 3) {
                    $productItemsPromotion[$productItem] = array(
                        'discountTotal' => 0,
                        'isFreeShipping' => 1,
                    );
                }
            }
            //if $discountAllTotal > $subtotal then return false
	        if($discountAllTotal > $subTotal){
	            return false;
	        }  
	                  
            return array('itemsDiscount' => $productItemsPromotion,
                          'discountAllTotal' => $discountAllTotal,
                          'stackable' => $promotion['stackable'],
                          'promotionId' =>  $promotion['id'],
                          'couponCode' =>  $couponCode,
                          'title' => $promotion['name']
                         );
        //}
    }

    private function getPromotionPrice($actionType,$actionValue,$normalPrice) {
        $discountPrice = 0;
        switch($actionType) {
            case 1:
                $discountPrice = number_format((100-$actionValue) * 0.01 * $normalPrice,3);
                break;
            case 4:
                $discountPrice = number_format((100-$actionValue) * 0.01 * $normalPrice,3);
                break;
            case 2:
                $discountPrice = number_format($normalPrice - $actionValue,3);
                break;
            case 5:
                $discountPrice = number_format($normalPrice - $actionValue,3);
                break;
            case 6:
                $discountPrice = number_format($normalPrice - $actionValue,3);
                break;
        }
        return $discountPrice;
    }

    /**
     * if total price(sale price * qty) > condition_value
     */
    public function processFreeShipping($total){
        $freeShipping = array();
        $freeShipping = $this->promotionDao->getPromotionFreeShippingInfo();
        if(!empty($freeShipping)){
            if( ($total + 0) >= ($freeShipping[0]['condition_value'] + 0) ){
                return $freeShipping[0]['condition_second_value'];
            }
        }
    	return 0;
    }
    
    
	/**
	 * give the category id to get the all item id
	 */
    public function getItemIdByCategoryId($categoryId){
        $result = $this->createTree($categoryId);
        $cid = $this->getCategoryId($result);
        $cids = $cid.$categoryId;//with their own input category id
        $item = $this->getItemId($cids);
        return $item;
    }
    
    public function createTree($parentId){ 
        $upc = array();
        $childCategory = $this->categoryDao->getByParentId($parentId);  
        if(!empty($childCategory)){
            foreach($childCategory as $category){
                $tempUpc = array();
                $tempUpc['id'] = $category['id'];
                $tempUpc['shortName'] = $category['short_name'];
                $tempUpc['fullName'] = $category['full_name'];
                $tempUpc['urlTitle'] = $category['url_title'];
                $child = $this->createTree($category['id']);
                $tempUpc['child'] = $child;
                $upc[] = $tempUpc;
            }
        }
        return $upc;
    } 
    
    public function getCategoryId($categories){
        $cid = "";
        if(!empty($categories)){
            foreach($categories as $category){
                $cid .= $category['id'].",";
                $children = $category['child'];
                if(!empty($children)){
                    $cid .= $this->getCategoryId($children);
                }
            }
        }
        return $cid;
    }
    
    public function getItemId($cids){
        $itemId = array();
        $itemInfo = $this->productItemDao->getItemInfoByCategoryIds($cids);
        foreach ($itemInfo as $item){
            $itemId[] = $item['itemId'];
        }
        return $itemId;
    }
    
    /**
     * log promotion
     */
    public function logPromotion($orderId,$usedPromotion,$userId) {
        if($usedPromotion != "") {
             $promotions = explode(",", $usedPromotion);
             $seq = 1;
             foreach ($promotions as $promotion) {
                 $param = array($orderId,$promotion,$seq);
                 $this->orderPromotionDao ->saveOrderPromotion($param);
                 $this->promotionDao -> updateUsedCount($promotion);
                 $seq++;
             }
         }
    }
    
    public function changeGiftLog($usedPromotionCode,$userId){
        if(!empty($usedPromotionCode) && $usedPromotionCode != "") {
             $promotionCodes = explode(",", $usedPromotionCode);
             foreach ($promotionCodes as $promotionCode) {
                  $data = array("status" => 6);
                  $this->applyGiftLogDao->updateApplyGiftLog($data,$promotionCode,$userId);
             }
         }    	
    }
    
    public function getUsedCountByCustomerAndPromotion($userId,$promotionId){
    	return $this->orderPromotionDao->getUsedCountByCustomerAndPromotion($userId,$promotionId);
    }
}
